#include "utility.h"
#include "math.h"
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

static const  char_t bcd2ascii[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
static const  uint8_t ascii2bcd1[10] = {0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u};
static const  uint8_t ascii2bcd2[6]  = {0x0Au, 0x0Bu, 0x0Cu, 0x0Du, 0x0Eu, 0x0Fu};

void ASC_to_BCD(uint8_t *bcd,  const uint8_t *asc, uint32_t len) {
    uint8_t c = 0u;
    uint8_t index = 0u;
    uint32_t i = 0u;

    len >>= 1;

    for(; i < len; i++) {
        /* first BCD */
        if((*asc >= (uint8_t)'A') && (*asc <= (uint8_t)'F')) {
            index = *asc - (uint8_t)'A';
            c  = (uint8_t)(ascii2bcd2[index] << 4u);
        } else if((*asc >= (uint8_t)'a') && (*asc <= (uint8_t)'f')) {
            index = *asc - (uint8_t)'a';
            c  = (uint8_t)(ascii2bcd2[index] << 4u);
        } else if((*asc >= (uint8_t)'0') && (*asc <= (uint8_t)'9')) {
            index = *asc - (uint8_t)'0';
            c  = (uint8_t)(ascii2bcd1[index] << 4u);
        }else{
        
        }
        
        asc++;

        /* second BCD */
        if((*asc >= (uint8_t)'A') && (*asc <= (uint8_t)'F')) {
            index = *asc - (uint8_t)'A';
            c  |= ascii2bcd2[index];
        } else if((*asc >= (uint8_t)'a') && (*asc <= (uint8_t)'f')) {
            index = *asc - (uint8_t)'a';
            c  |= ascii2bcd2[index];
        } else if((*asc >= (uint8_t)'0') && (*asc <= (uint8_t)'9')) {
            index = *asc - (uint8_t)'0';
            c  |= ascii2bcd1[index];
        }else{
        
        }
        
        asc++;

        *bcd++ = c;
    }
}

uint64_t BCD_to_Dec(const uint8_t *bcd, uint32_t len) 
{
    uint32_t i,tmp;
    uint64_t dec = 0u;
    for (i = 0u; i < len; i++)
    {
        tmp = (uint32_t)((((uint32_t)bcd[i] >> 4u) & 0x0Fu) * 10u) + ((uint32_t)bcd[i] & 0x0Fu); 
        dec += tmp * pow(100, (len - 1 - i)); 
    }
    return dec; 
}

void BCD_to_ASC (uint8_t *asc, const uint8_t *bcd, uint32_t len) {
    uint8_t c = 0u;
    uint32_t i;

    for(i = 0u; i < len; i++) {
        /* first BCD */
        c = *bcd >> 4;
        *asc++ = bcd2ascii[c];

        /* second */
        c = *bcd & 0x0f;
        *asc++ = bcd2ascii[c];
        bcd++;
    }
}

uint32_t ut_getword(const uint8_t *buf, int32_t *pos){
    uint32_t word = ((uint32_t)buf[*pos+3]<<24) | ((uint32_t)buf[*pos+2] << 16) | ((uint32_t)buf[*pos+1] << 8) | (uint32_t)buf[*pos];
    *pos += 4;
	return word;
}

uint16_t ut_getshort(const uint8_t *buf, int32_t *pos) {
    uint16_t halfword =  ((uint16_t)buf[*pos+1] << 8) | (uint16_t)buf[*pos];
    *pos += 2;
	return halfword;
}

uint8_t ut_getbyte(const uint8_t *buf, int32_t *pos) {
    uint8_t byte = buf[*pos];
	*pos += 1;
    return byte;
}

int32_t ut_getnbyte(const uint8_t *buf, int32_t *pos, uint8_t *data, int32_t len) {
    memcpy(data, buf, len);
	*pos += len;
    return *pos;
}

int32_t ut_setword(uint8_t *buf, int32_t pos, uint32_t data) {
    buf[pos] = (uint8_t)data;
    buf[pos + 1] = (uint8_t)(data >> 8);
    buf[pos + 2] = (uint8_t)(data >> 16);
    buf[pos + 3] = (uint8_t)(data >> 24);
    return pos + 4;
}

int32_t ut_setshort(uint8_t *buf, int32_t pos, uint16_t data) {
    buf[pos] = (uint8_t)data;
    buf[pos + 1] = (uint8_t)(data >> 8);
    return pos + 2;
}

int32_t ut_setbyte(uint8_t *buf, int32_t pos, uint8_t data) {
    buf[pos] = data;
    return pos + 1;
}

int32_t ut_setnbyte(uint8_t *buf, int32_t pos, const uint8_t *data, int32_t len) {
	memcpy(&buf[pos], data, len);
	return pos + len;
}

void ut_atom_num(char_t *buf,  int64_t n, int32_t fmt){
	char_t str[43];
	char_t *s = str +sizeof(str);
	uint64_t m;
	if (n == LONG_MIN)
		m = LONG_MAX +1UL;
	else if (n<0)
		m = -n;
	else
		m = n;
		
	do{
        if (m%fmt >= 10){
            *--s = (m%fmt)-10 + 'a';
        }else{
            *--s = m%fmt + '0';
        }
    }
	while ((m/=fmt)>0);
    
	if ((fmt == 10) && (n<0))
		*--s = '-';
	memcpy(buf, s, (str + sizeof(str))-s);
}

void ut_itostr(uint32_t val, char_t *buf, int32_t fmt){
    ut_atom_num(buf, (int64_t)val, fmt);
}

struct Item {
    const char_t *begin;
    uint32_t len;
    char_t *next;
};

static void get_cmd_item(const char_t *buf, const char_t *delim, struct Item *item) {
    char_t *end;
    if (item->begin == NULL) {
        item->begin = buf;
    } else if (item->next != NULL) {
        item->begin = item->next;
    }else{
    
    }

    //返回s中第一个不在accept中出现的字符下标
    item->begin += strspn(item->begin, delim);
    if (*item->begin == '\0') {
        item->len = 0;
    }else{
        //返回delim中字符在str1中的位置的指针
        end = strpbrk(item->begin, delim);
        if (end == NULL) {
            item->next = strchr(item->begin, '\0');
            item->len = (uint32_t)(item->next - item->begin);
        } else {
            item->next = end + 1;
            item->len = (uint32_t)(end - item->begin);
        }
    }
}

void _get_cmd_str(const char_t *buf, const char_t *cmd, char_t *value, int32_t len) {
    struct Item item = {0};
    uint32_t copy_len;
    
    get_cmd_item(buf, "&", &item);
    while(item.len != 0) {
        struct Item itemcmd = {0};
        get_cmd_item(item.begin, "=", &itemcmd);
        if (itemcmd.len != 0 && (strlen(item.next) == 0 || itemcmd.next < (item.next - 1)) && itemcmd.len == strlen(cmd)
                && strncmp(cmd, itemcmd.begin, itemcmd.len) == 0) {
            copy_len = (((item.len - strlen(cmd)) - 1) >= (uint32_t)len) ? ((uint32_t)len - 1) : ((item.len - strlen(cmd)) - 1);
            strncpy(value, itemcmd.next, copy_len);
            return;
        }

        get_cmd_item(buf, "&", &item);
    }
}

uint32_t get_cmd_value(const char_t *str, const char_t *cmd) {
    char_t buf[32] = {0};
    uint32_t val = 0;
    get_cmd_str(str, cmd, buf);
    if (strlen(buf) != 0) {
        val = (uint32_t)strtol(buf, NULL, 10);
    }
    return val;
}
//浮点数都转换成*100的整数
uint32_t get_cmd_float(const char_t *str, const char_t *cmd) {
    char_t buf[32] = {0};
    uint32_t val = 0;
    get_cmd_str(str, cmd, buf);
    if (strlen(buf) != 0) {
        val = (uint32_t)(strtof(buf, NULL)*100);
    }
    return val;
}
    
void set_cmd_str(char_t *str, const char_t *cmd, const char_t *value) {
    strcat(str, cmd);
    strcat(str, value);
}

void set_cmd_value(char_t *str, const char_t *cmd, uint32_t value) {
    char buf[43] = {0};
    snprintf(buf, sizeof(buf), "%u", (int32_t)value);
    strcat(str, cmd);
    strcat(str, buf);
}

void set_cmd_hex(char_t *str, const char_t *cmd, uint32_t value) {
    char buf[43] = {0};
    snprintf(buf, sizeof(buf), "%x", value);
    strcat(str, cmd);
    strcat(str, buf);
}

//浮点数都转换成*100的整数
void set_cmd_float(char *str, const char *cmd, uint32_t value) {
    char buf[43] = {0};
    snprintf(buf, sizeof(buf), "%d.%02d", value/100, value%100);
    strcat(str, cmd);
    strcat(str, buf);
}

//len 为bcd的长度
void set_cmd_bcd(char *str, const char *cmd, const char_t *value, uint32_t len){
    char_t buf[50] = {0};
    strcat(str, cmd);
    BCD_to_ASC((uint8_t *)buf, (uint8_t *)value, len);
    strcat(str, buf);
}

//len 为bcd的长度
void get_cmd_bcd(const char *str, const char *cmd, char_t *value, uint32_t len){
    char_t buf[50] = {0};
    get_cmd_str(str, cmd, buf);
    ASC_to_BCD((uint8_t *)value, (uint8_t *)buf, strlen(buf));
}

int32_t str_equal(const char_t *src, const char_t *dst) {
    int32_t ret = 0;
    if (strncmp(src, dst, strlen(dst)) == 0){
        ret = 1;
    }
    return ret;
}

int32_t get_cmd_cost(const char_t *str, uint16_t *charge_fee, uint16_t *service_fee, int32_t len){
    struct Item item = {0};
    uint32_t i = 0;
    
    if (strlen(str) == 0){
        return -1;
    }
    get_cmd_item(str, ",", &item);
    while(item.len != 0) {
        struct Item itemcmd = {0};
        get_cmd_item(item.begin, "-", &itemcmd);
        if (itemcmd.len != 0 && (strlen(item.next) == 0 || itemcmd.next < (item.next - 1))){
            char_t elec_str[20]={0};
            char_t serv_str[20]={0};
            memcpy(elec_str, item.begin, (itemcmd.len>sizeof(elec_str)) ? sizeof(elec_str)-1 : itemcmd.len);
            memcpy(serv_str, itemcmd.next, ((item.len-itemcmd.len-1)>sizeof(serv_str))? sizeof(serv_str)-1 : item.len-itemcmd.len-1);
            charge_fee[i] = strtol(elec_str, NULL, 10);
            service_fee[i] = strtol(serv_str, NULL, 10);
            printf("charge_fee[%02d]:%d, elec_str:%s serve_fee:%d serv_fee:%s\r\n", i, charge_fee[i], elec_str, service_fee[i], serv_str);
            i++;
            if (i >= len){
                return -1;
            }
        }

        get_cmd_item(str, ",", &item);
    }  
    return 0;
}

int32_t get_tzone_value(const char *str, uint16_t *value, int32_t len){
    struct Item item = {0};
    int32_t i = 0;
    if (strlen(str) == 0){
        return -1;
    }
    get_cmd_item(str, ",", &item);
    while(item.len != 0){
        char_t str[20]={0};
        int32_t val = 0;
        int32_t dec = 0;
        memcpy(str, item.begin, item.len);
        sscanf(str, "%d.%d", &val, &dec);
        value[i++] = val*100+dec;
        get_cmd_item(str, ",", &item);
        if (i >= len){
            break;
        }
    }
    return 0;
}

void print_chr(char_t chr){
    if(isprint(chr)){
        printf("%c", chr);
    }else{
        printf("{%02x}", chr);
    }
}

void print_str(const char_t *str, int32_t len){
    for(int32_t i=0;i<len;i++){
        print_chr(str[i]);
    }
    printf("\r\n");
}
